<template>
  <!-- html 结构 -->
  <div class="person">
    <h1>情况四：监视【reactive】定义的【对象类型】类数据的内部对象</h1>
    <h2>姓名：{{ person.name }}</h2>
    <h2>年龄：{{ person.age }}</h2>
    <h2>汽车：{{ person.car.c1 }}、{{ person.car.c2 }}</h2>
    <button @click="changeName">修改姓名</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1">修改第一辆汽车</button>
    <button @click="changeC2">修改第二辆汽车</button>
    <button @click="changeCar">修改所有的汽车</button>
    <hr />
  </div>
</template>

<!-- 在vue3中监事一个reactive定义的响应式常量应该是这么写的 -->
<script lang="ts" setup name="Person">
import { reactive, watch } from "vue";
// 数据
let person = reactive({
  name: "张三",
  age: 19,
  car: {
    c1: "奔驰",
    c2: "宝马",
  },
});

function changeName() {
  person.name += "~";
}
function changeAge() {
  person.age += 1;
}
function changeC1() {
  person.car.c1 += "~";
}
function changeC2() {
  person.car.c2 += "~";
}
function changeCar() {
  person.car = { c1: "大奔", c2: "大迪子" };
}

// 监听整个对象
// watch(person, (newValue, oldValue) => {
//   console.log("person变化了", newValue, oldValue);
// });

// 监听某个属性的变化
/**  总结一下watch能监听的4总类型：
 * 1、ref修饰的基本类型和对象类型
 * 2、reactive修饰的对象类型
 * 3、一个函数，返回一个值
 * 4、由以上类型组成的数组
 */

// 监视响应对象中的某个属性，且该属性是基本类型，只能写函数式: ()=>person.name
// watch(
//   () => {
//     return person.name;
//   },
//   (newValue, oldValue) => {
//     console.log("person.name变化了", newValue, oldValue);
//   }
// );

// 监听响应式对象中的某个属性，且该属性是对象类型，可以直接写也可以写函数式，更推荐函数式，不过要监听该对象中的某个属性时需要开启深度监听
// 从这里就可以看出一个问题：那就是监听对象默认监听的是对象的地址值是否发生变化，如果需要监听对象内部属性就需要开启深度监听
watch(
  () => person.car,
  (newValue, oldValue) => {
    console.log("person.car变化了", newValue, oldValue);
  },
  { deep: true }
);

watch([() => person.name, () => person.car], (newValue, oldValue) => {
  console.log("监视多个数据", newValue, oldValue);
});
</script>

<style>
/* 样式 */
button {
  background-color: aqua;
  margin: 5px;
}
</style>
